老大最近说公司要开始做新的项目,给一些相关 IM 通信方面的资料。目前仅仅对 Socket 和 WebSocket 一些基本知识进行整理。
下面整理出 HTTP/IP 相关知识思维导图

Socket简介
Socket起源
Socket 是一种文件描述,起源于 Unix。所以 Socket 采用 Unix 一切皆文件核心,符合 打开 open –>读写 write/read –> 关闭 close 模式。
Socket又被称为:套接字。在网络中两个进行进行通信 Socket 是其基石,同时也是支持 TCP/IP 协议的网络通信的基本单元。Socket本质来说不是协议而是对于 TCP/IP 的抽象,包含网络通信的物种基本信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
TCP/IP 基础知识
小编在此向大家简单的介绍一些关于 TCP/IP 基本知识。从字面上来说 TCP/IP 是两种协议,但是我们通常依次来代指整个 TCP/IP 协议族代称。我们在 ISO 模型分为七层,但是在 TCP/IP 协议分为四层:应用层、传输层、网络层和数据链路层。
下面列举每层一些相关协议:
- 应用层:
HTTP,FTP,SMTP,DNS,Telnet等 - 传输层:
UDP,TCP - 网络层:
IGMP,ICMP,IP - 数据链路层:
MTU,SLIP,CSLIP,PPP等
上面的四层网络从高到低,每一层抽象层都是是建立在低一层的服务上面并且为高层提供服务。
下面给出在 TCP/IP 和 ISO 分层结构和关系图:

【图片来源于网络】

【图片来源于网络】
Socket使用
小编在上面介绍过 Socket 基本概念和 TCP/IP 一些基本知识,下面将介绍 Socket 一些实现流程、使用和实现的原理。
使用流程
Socket在TCP/IP分层应用
上文小编提到 Socket 是对 TCP/IP 的一些封装,下面给出图来详细介绍:

Socket通信流程

由上图我们看出 Socket 信息交互流程:
(1)服务器(server)根据地质类型(IPV4/IPV6)和
Socket类型,协议创建Socket;
(2)server 绑定Socket和 宿主源的端口号以及 IP 地址;
(3)server 监听上述绑定的端口,随时接受Socket请求。但此时并没有开启Socket;
(4)客户端(client) 创建Socket;
(5)client 指定源的端口和 IP 地址,并申请链接;
(6)server 接收到请求链接请求被动打开,开始jieshou客户端请求。这时accept处于阻塞状态,知道 client 信息返回后才可以接受下一个Socket;
(7)client 向 server 向Socket发送细信息;
(8)server 接受Socket读取其中的信息;
(9)client 关闭Socket;
(10)server 关闭Socket。
在上述(5)~(6)过程瞒住我们在 TCP 中见到的经典的三次握手🤝如下图:

第一次握手:客户端尝试连接服务器,向服务器发送
syn包(同步序列编号Synchronize Sequence Numbers),syn=j,客户端进入SYN_SEND状态等待服务器确认第二次握手:服务器接收客户端
syn包并确认(ack=j+1),同时向客户端发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态第三次握手:客户端收到服务器的
SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手
Socket API
小编简单了解一下socket提供了哪些API供应用程序使用,还是以TCP协议为例,看看Unix下的socket API,小编这里就简单解释一下方法作用和参数。
1 | int socket(int domain, int type, int protocol); |
根据指定的地址族、数据类型和协议来分配一个socket的描述字及其所用的资源。
domain: 协议族。常用的有AF_INET、AF_INET6、AF_LOCAL、AF_ROUTE其中AF_INET代表使用ipv4地址;
type:socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等
protocol:协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等
1 | int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); |
把一个地址族中的特定地址赋给socket。
sockfd:socket描述字,也就是socket引用
addr:要绑定给sockfd的协议地址
addrlen:地址的长度
通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。
1 | int listen(int sockfd, int backlog); |
监听socket。
sockfd:要监听的socket描述字
backlog:相应socket可以排队的最大连接个数
1 | int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); |
连接某个socket。
sockfd:客户端的socket描述字
addr:服务器的socket地址
addrlen:socket地址的长度
1 | int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); |
TCP服务器监听到客户端请求之后,调用accept()函数取接收请求。
sockfd:服务器的socket描述字
addr:客户端的socket地址
addrlen:socket地址的长度
1 | ssize_t read(int fd, void *buf, size_t count); |
读取socket内容。
fd:socket描述字
buf:缓冲区
count:缓冲区长度
1 | ssize_t write(int fd, const void *buf, size_t count); |
向socket写入内容,其实就是发送内容。
fd:socket描述字
buf:缓冲区
count:缓冲区长度
1 | int close(int fd); |
socket标记为以关闭 ,使相应socket描述字的引用计数-1,当引用计数为0的时候,触发TCP客户端向服务器发送终止连接请求。
参考地址:
socket实现原理和机制
Java TCP/IP Socket 编程
Socket.md
Linux Socket编程(不限Linux)